// Copyright (c) 2022 NetEase, Inc. All rights reserved.
// Use of this source code is governed by a MIT license that can be
// found in the LICENSE file.

package com.netease.yunxin.kit.chatkit.ui.view.input;

import static com.luoxiang.lib_common.common.Constants.MmkvConst.ACCID;
import static com.luoxiang.lib_common.common.Constants.MmkvConst.EXTRA;
import static com.luoxiang.lib_common.common.Constants.MmkvConst.KEY;
import static com.luoxiang.lib_common.common.Constants.MmkvConst.TOKEN;

import android.Manifest;
import android.annotation.SuppressLint;
import android.app.Activity;
import android.content.Context;
import android.text.Editable;
import android.text.TextUtils;
import android.text.TextWatcher;
import android.util.AndroidException;
import android.util.AndroidRuntimeException;
import android.util.AttributeSet;
import android.util.Log;
import android.view.KeyEvent;
import android.view.LayoutInflater;
import android.view.MotionEvent;
import android.view.View;
import android.view.ViewConfiguration;
import android.view.inputmethod.EditorInfo;
import android.widget.FrameLayout;
import android.widget.Toast;

import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
import androidx.fragment.app.FragmentActivity;
import androidx.recyclerview.widget.LinearLayoutManager;
import androidx.recyclerview.widget.RecyclerView;

import com.google.android.material.bottomsheet.BottomSheetDialog;
import com.google.gson.Gson;
import com.jeremyliao.liveeventbus.LiveEventBus;
import com.luoxiang.lib_common.bean.ImCallbackDTO;
import com.luoxiang.lib_common.bean.NumberBean;
import com.luoxiang.lib_common.bean.ResponseDTO;
import com.luoxiang.lib_common.utils.AESUtil;
import com.luoxiang.lib_common.utils.MmkvUtil;
import com.luoxiang.lib_common.utils.NetUtils;
import com.lxj.xpopup.XPopup;
import com.netease.nim.highavailable.LogUtils;
import com.netease.nimlib.sdk.NIMClient;
import com.netease.nimlib.sdk.media.record.IAudioRecordCallback;
import com.netease.nimlib.sdk.media.record.RecordType;
import com.netease.nimlib.sdk.msg.MsgService;
import com.netease.nimlib.sdk.msg.attachment.AudioAttachment;
import com.netease.nimlib.sdk.msg.attachment.MsgAttachment;
import com.netease.nimlib.sdk.msg.constant.AttachStatusEnum;
import com.netease.nimlib.sdk.msg.constant.MsgDirectionEnum;
import com.netease.nimlib.sdk.msg.constant.MsgStatusEnum;
import com.netease.nimlib.sdk.msg.constant.MsgTypeEnum;
import com.netease.nimlib.sdk.msg.constant.SessionTypeEnum;
import com.netease.nimlib.sdk.msg.model.CustomMessageConfig;
import com.netease.nimlib.sdk.msg.model.IMMessage;
import com.netease.nimlib.sdk.msg.model.MemberPushOption;
import com.netease.nimlib.sdk.msg.model.MsgThreadOption;
import com.netease.nimlib.sdk.msg.model.NIMAntiSpamOption;
import com.netease.nimlib.sdk.msg.model.NIMMessage;
import com.netease.nimlib.sdk.msg.model.RecentContact;
import com.netease.yunxin.kit.alog.ALog;
import com.netease.yunxin.kit.chatkit.ui.FunctionInterface;
import com.netease.yunxin.kit.chatkit.ui.R;
import com.netease.yunxin.kit.chatkit.ui.bean.BeforeCallBean;
import com.netease.yunxin.kit.chatkit.ui.bean.GiftMessageBean;
import com.netease.yunxin.kit.chatkit.ui.common.MessageHelper;
import com.netease.yunxin.kit.chatkit.ui.common.MessageUtil;
import com.netease.yunxin.kit.chatkit.ui.custom.GiftAttachment;
import com.netease.yunxin.kit.chatkit.ui.custom.StickerAttachment;
import com.netease.yunxin.kit.chatkit.ui.databinding.ChatMessageBottomLayoutBinding;
import com.netease.yunxin.kit.chatkit.ui.dialog.GiftDialog;
import com.netease.yunxin.kit.chatkit.ui.model.ChatMessageBean;
import com.netease.yunxin.kit.chatkit.ui.view.ait.AitTextChangeListener;
import com.netease.yunxin.kit.chatkit.ui.view.emoji.IEmojiSelectedListener;
import com.netease.yunxin.kit.chatkit.ui.view.interfaces.IMessageProxy;
import com.netease.yunxin.kit.common.ui.action.ActionItem;
import com.netease.yunxin.kit.common.ui.utils.ToastUtils;
import com.netease.yunxin.kit.common.ui.viewmodel.FetchResult;
import com.netease.yunxin.kit.common.ui.viewmodel.LoadStatus;
import com.netease.yunxin.kit.common.utils.KeyboardUtils;
import com.netease.yunxin.kit.common.utils.NetworkUtils;
import com.netease.yunxin.kit.conversationkit.model.ConversationInfo;
import com.netease.yunxin.kit.conversationkit.repo.ConversationRepo;
import com.netease.yunxin.kit.conversationkit.ui.common.XLog;
import com.netease.yunxin.kit.conversationkit.ui.model.ConversationBean;
import com.netease.yunxin.kit.corekit.im.IMKitClient;
import com.netease.yunxin.kit.corekit.im.provider.FetchCallback;
import com.netease.yunxin.nertc.ui.CallKitUI;
import com.netease.yunxin.nertc.ui.base.CallParam;

import java.io.File;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import java.util.UUID;

import io.reactivex.Observer;
import io.reactivex.android.schedulers.AndroidSchedulers;
import io.reactivex.disposables.Disposable;
import io.reactivex.schedulers.Schedulers;
import kotlin.Unit;
import kotlin.jvm.functions.Function1;

public class MessageBottomLayout extends FrameLayout
        implements IAudioRecordCallback, AitTextChangeListener {
    public static final String TAG = "MessageBottomLayout";
    private static final long SHOW_DELAY_TIME = 200;
    private static final int ACTION_COUNT_MAX = 5;
    private ChatMessageBottomLayoutBinding mBinding;
    private InputActionAdapter actionAdapter;
    private IMessageProxy mProxy;
    private String mEdieNormalHint = "发消息";
    private boolean mMute = false;
    private String accidtouserid, account;
    ChatMessageBean replyMessage;
    private androidx.lifecycle.Observer<MsgAttachment> observer;

    private final ActionsPanel mActionsPanel = new ActionsPanel();
    private TextWatcher aitTextWatcher;

    private boolean isKeyboardShow = false;
    private InputState mInputState = InputState.none;
    private IEmojiSelectedListener emojiSelectedListener;

    public MessageBottomLayout(@NonNull Context context) {
        this(context, null);
    }

    public MessageBottomLayout(@NonNull Context context, @Nullable AttributeSet attrs) {
        this(context, attrs, 0);
    }

    public MessageBottomLayout(
            @NonNull Context context, @Nullable AttributeSet attrs, int defStyleAttr) {
        super(context, attrs, defStyleAttr);
        initView();
    }

    public void init(IMessageProxy proxy) {
        this.init(ActionFactory.assembleDefaultInputActions(), proxy);
    }

    public void init(List<ActionItem> items, IMessageProxy proxy) {
//        mBinding.iconSendvoice.setOnClickListener(new OnClickListener() {
//            @Override
//            public void onClick(View view) {
//                switchRecord();
//                Log.i("show", "点击了");
//            }
//        });
        accidtouserid = MmkvUtil.INSTANCE.decodeString("accidtouser");//对方id
        mProxy = proxy;
        items = items.size() > ACTION_COUNT_MAX ? items.subList(0, ACTION_COUNT_MAX) : items;
        actionAdapter =
                new InputActionAdapter(
                        items,
                        (position, item) -> {
                            ALog.d(TAG, "action click, inputState:" + mInputState);
                            switch (item.getType()) {
//                                case ActionConstants.ACTION_TYPE_RECORD://原本语音已注释
//                                    switchRecord();
//                                    break;
                                case ActionConstants.ACTION_TYPE_EMOJI://表情
                                    switchEmoji();
                                    break;
                                case ActionConstants.ACTION_TYPE_ALBUM://视频原本为选择照片
                                    if (TextUtils.equals(accidtouserid, "100000")){
                                        onAlbumClick();
                                    }else{
                                        String s = MmkvUtil.INSTANCE.decodeString(TOKEN);
                                        account = IMKitClient.account();//我的id
                                        Log.i("accoutid", account);
                                        getimPre(EXTRA, accidtouserid, s);
                                    }
//                                    onAlbumClick();
                                    break;
//                                case ActionConstants.ACTION_TYPE_FILE://原本
////                                    mProxy.sendFile(replyMessage);
////                                    clearReplyMsg();
//                                    break;
                                case ActionConstants.ACTION_TYPE_MORE://送礼物,原本为+号
                                    GiftDialog giftDialog = new GiftDialog(getContext(), accidtouserid, 1, "0");
                                    new XPopup.Builder(getContext())
                                            .moveUpToKeyboard(true)
                                            .asCustom(giftDialog)
                                            .show();
                                    giftDialog.setOnSendSuccess(giftMessageBean -> {
                                        MsgAttachment attachment = new GiftAttachment(giftMessageBean);
                                        mProxy.sendCustomMessage(
                                                attachment, "[礼物消息]");
                                        return null;
                                    });
                                    break;
                                default:
                                    break;
                            }
                        });
        actionAdapter.disableAll(mMute);
        mBinding.chatMessageActionContainer.setAdapter(actionAdapter);
        mBinding.chatMessageRecordView.setRecordCallback(this);
        mBinding.chatMessageRecordView.setPermissionRequest(
                permission -> {
                    if (mProxy.hasPermission(Manifest.permission.RECORD_AUDIO)) {
                        return true;
                    }
                    return false;
                });

        emojiSelectedListener =
                new IEmojiSelectedListener() {
                    @Override
                    public void onEmojiSelected(String key) {
                        Editable mEditable = mBinding.chatMessageInputEt.getText();
                        if (key.equals("/DEL")) {
                            mBinding.chatMessageInputEt.dispatchKeyEvent(
                                    new KeyEvent(KeyEvent.ACTION_DOWN, KeyEvent.KEYCODE_DEL));
                        } else {
                            int start = mBinding.chatMessageInputEt.getSelectionStart();
                            int end = mBinding.chatMessageInputEt.getSelectionEnd();
                            start = Math.max(start, 0);
                            mEditable.replace(start, end, key);
                        }
                    }

                    @Override
                    public void onStickerSelected(String categoryName, String stickerName) {
                        MsgAttachment attachment = new StickerAttachment(categoryName, stickerName);
                        mProxy.sendCustomMessage(
                                attachment, getContext().getString(R.string.chat_message_custom_sticker));
                    }

                    @Override
                    public void onEmojiSendClick() {
                        sendText(replyMessage);
                    }
                };

        mBinding.llyReply.setVisibility(GONE);
        // init more panel
        mActionsPanel.init(
                mBinding.chatMessageActionsPanel, ActionFactory.assembleInputMoreActions(), mProxy);

        mBinding.chatMessageInputEt.setOnFocusChangeListener((v, hasFocus) -> mProxy.onTypeStateChange(
                !TextUtils.isEmpty(mBinding.chatMessageInputEt.getText()) && hasFocus));

        mBinding.chatMessageInputEt.addTextChangedListener(
                new TextWatcher() {
                    @Override
                    public void beforeTextChanged(CharSequence s, int start, int count, int after) {
                    }

                    @Override
                    public void onTextChanged(CharSequence s, int start, int before, int count) {
                        mProxy.onTypeStateChange(!TextUtils.isEmpty(s));
                    }

                    @Override
                    public void afterTextChanged(Editable s) {
                    }
                });

    }

    private void getImPreChat(String type, String message, FunctionInterface functionInterface) {
        String toUserId = MmkvUtil.INSTANCE.decodeString("accidtouser");
        String token = MmkvUtil.INSTANCE.decodeString(TOKEN);
        NetUtils.getInstance().getApiService().getImPreChat(token, toUserId, type, message)
                .subscribeOn(Schedulers.io())
                .observeOn(AndroidSchedulers.mainThread())
                .subscribe(new Observer<NumberBean>() {
                    @Override
                    public void onSubscribe(Disposable d) {

                    }

                    @Override
                    public void onNext(NumberBean numberBean) {
                        String data = numberBean.getData();
                        String decryptStr = null;
                        try {
                            decryptStr = AESUtil.aesDecryptString(data, KEY);
                            Log.i("decryptStr10", decryptStr);
                        } catch (Exception e) {
                            e.printStackTrace();
                        }
                        Gson gson = new Gson();
                        ResponseDTO responseDTO = gson.fromJson(decryptStr, ResponseDTO.class);
                        if (responseDTO == null) {
                            return;
                        }
                        if (responseDTO.getCode() == 0) {
                            functionInterface.invoke();
                        } else {
                            Toast.makeText(getContext(), responseDTO.getMsg(), Toast.LENGTH_SHORT).show();
                        }
                    }

                    @Override
                    public void onError(Throwable e) {

                    }

                    @Override
                    public void onComplete() {

                    }
                });

    }

    private void getimPre(String extra, String toUserId, String token) {
        Log.i("toUserId --> ", toUserId);
        NetUtils.getInstance().getApiService().getimPre(extra, toUserId, token)
                .subscribeOn(Schedulers.io())
                .observeOn(AndroidSchedulers.mainThread())
                .subscribe(new Observer<NumberBean>() {
                    @Override
                    public void onSubscribe(Disposable d) {

                    }

                    @Override
                    public void onNext(NumberBean numberBean) {
                        String data = numberBean.getData();
                        String decryptStr = null;
                        try {
                            decryptStr = AESUtil.aesDecryptString(data, KEY);
                            Log.i("decryptStr10", decryptStr);
                        } catch (Exception e) {
                            e.printStackTrace();
                        }
                        Gson gson = new Gson();
                        BeforeCallBean bean = gson.fromJson(decryptStr, BeforeCallBean.class);
                        if (bean.getCode() == 0) {
                            //生成房间号
                            String id = UUID.randomUUID().toString().replace("-","");
                            //可以发起通话
                            CallParam param = CallParam.createSingleCallParam(2, account, accidtouserid,null,null,id);
                            CallKitUI.startSingleCall(getContext(), param);
                        } else {
                            ToastUtils.INSTANCE.showShortToast(getContext(), bean.getMsg());
                        }
                    }

                    @Override
                    public void onError(Throwable e) {

                    }

                    @Override
                    public void onComplete() {

                    }
                });

    }

    public void getGift() {

    }

    public void setAitTextWatcher(TextWatcher aitTextWatcher) {
        this.aitTextWatcher = aitTextWatcher;
    }

    public void updateInputInfo(String name) {
        mBinding.chatMessageInputEt.setHint(mEdieNormalHint);
    }

    @SuppressLint("ClickableViewAccessibility")
    private void initView() {
        mBinding =
                ChatMessageBottomLayoutBinding.inflate(LayoutInflater.from(getContext()), this, true);
        getViewTreeObserver()
                .addOnGlobalLayoutListener(
                        () -> {
                            if (KeyboardUtils.isKeyboardShow((Activity) getContext())) {
                                if (!isKeyboardShow) {
                                    onKeyboardShow();
                                    isKeyboardShow = true;
                                }
                            } else {
                                if (isKeyboardShow) {
                                    onKeyboardHide();
                                    isKeyboardShow = false;
                                }
                            }
                        });
        // input view
        mBinding.chatMessageInputEt.addTextChangedListener(
                new TextWatcher() {
                    private int start;
                    private int count;

                    @Override
                    public void beforeTextChanged(CharSequence s, int start, int count, int after) {
                        if (aitTextWatcher != null) {
                            aitTextWatcher.beforeTextChanged(s, start, count, after);
                        }
                    }

                    @Override
                    public void onTextChanged(CharSequence s, int start, int before, int count) {
                        this.start = start;
                        this.count = count;
                        if (aitTextWatcher != null) {
                            aitTextWatcher.onTextChanged(s, start, before, count);
                        }
                    }

                    @Override
                    public void afterTextChanged(Editable s) {
                        MessageUtil.replaceEmoticons(getContext(), s, start, count);
                        if (aitTextWatcher != null) {
                            aitTextWatcher.afterTextChanged(s);
                        }
                    }
                });
        mBinding.chatMessageInputEt.setOnTouchListener(
                (v, event) -> {
                    if (event.getAction() == MotionEvent.ACTION_DOWN) {
                        switchInput();
                    }
                    return false;
                });
        mBinding.chatMessageInputEt.setOnEditorActionListener(
                (v, actionId, event) -> {
                    if (actionId == EditorInfo.IME_ACTION_SEND) {
                        sendText(replyMessage);
                    }
                    return true;
                });

        mBinding.chatMessageEmojiView.setWithSticker(true);
        // action
        mBinding.chatMessageActionContainer.setLayoutManager(
                new LinearLayoutManager(getContext(), RecyclerView.HORIZONTAL, false));
        mBinding.btnSendmeaage.setOnClickListener(new OnClickListener() {
            @Override
            public void onClick(View view) {
                getImPreChat("1", mBinding.chatMessageInputEt.getText().toString(), () -> {
                    sendText(replyMessage);
                });
            }
        });
        mBinding.iconSendvoice.setOnClickListener(new OnClickListener() {
            @Override
            public void onClick(View view) {
                getImPreChat("2", null, () -> switchRecord());
            }
        });
    }

    private void sendText(ChatMessageBean replyMessage) {
        String msg = mBinding.chatMessageInputEt.getEditableText().toString();
        if (!TextUtils.isEmpty(msg) && mProxy != null) {
            if (mProxy.sendTextMessage(msg, replyMessage)) {
                AudioAttachment audioAttachment = new AudioAttachment();
                mBinding.chatMessageInputEt.setText("");
                clearReplyMsg();
            }
        }
    }

    private void hideCurrentInput() {
        if (mInputState == InputState.input) {
            hideKeyboard();
        } else if (mInputState == InputState.voice) {
            recordShow(false, 0);
        } else if (mInputState == InputState.emoji) {
            emojiShow(false, 0);
        } else if (mInputState == InputState.more) {
            morePanelShow(false, 0);
        }
    }

    private void switchInput() {
        if (mInputState == InputState.input) {
            return;
        }
        hideCurrentInput();
        showKeyboard();
        mInputState = InputState.input;
    }

    private void switchRecord() {
        if (mInputState == InputState.voice) {
            recordShow(false, 0);
            mInputState = InputState.none;
            return;
        }
        recordShow(true, 0);
        hideCurrentInput();
        mInputState = InputState.voice;
    }

    private void recordShow(boolean show, long delay) {
        postDelayed(() -> mBinding.chatMessageRecordView.setVisibility(show ? VISIBLE : GONE), delay);
        actionAdapter.updateItemState(ActionConstants.ACTION_TYPE_RECORD, show);
    }

    private void switchEmoji() {
        if (mInputState == InputState.emoji) {
            emojiShow(false, 0);
            mInputState = InputState.none;
            return;
        }
        emojiShow(true, 0);
        hideCurrentInput();
        mInputState = InputState.emoji;
    }

    private void emojiShow(boolean show, long delay) {
        postDelayed(
                () -> {
                    mBinding.chatMessageEmojiView.setVisibility(show ? VISIBLE : GONE);
                    if (show) {
                        mBinding.chatMessageEmojiView.show(emojiSelectedListener);
                    }
                },
                delay);
        actionAdapter.updateItemState(ActionConstants.ACTION_TYPE_EMOJI, show);
    }

    private void switchMore() {
        if (mInputState == InputState.more) {
            morePanelShow(false, 0);
            mInputState = InputState.none;
            return;
        }
        morePanelShow(true, 0);
        hideCurrentInput();
        mInputState = InputState.more;
    }

    private void morePanelShow(boolean show, long delay) {
        postDelayed(() -> mBinding.chatMessageActionsPanel.setVisibility(show ? VISIBLE : GONE), delay);
        actionAdapter.updateItemState(ActionConstants.ACTION_TYPE_MORE, show);
    }

    private void onAlbumClick() {
        if (mInputState == InputState.input) {
            hideKeyboard();
            postDelayed(() -> mProxy.pickMedia(), SHOW_DELAY_TIME);
        } else {
            mProxy.pickMedia();
        }
    }

    public void setMute(boolean mute) {
        mMute = mute;
        mBinding.chatMessageInputEt.setEnabled(!mute);
        mBinding.chatMessageInputEt.setText("");
        String hint = mute ? getContext().getString(R.string.chat_team_all_mute) : mEdieNormalHint;
        mBinding.chatMessageInputEt.setHint(hint);
        if (mute) {
            collapse(true);
        }
        mBinding.chatMessageInputLayout.setBackgroundResource(
                mute ? R.color.color_e3e4e4 : R.color.color_white);
        if (actionAdapter != null) {
            actionAdapter.disableAll(mute);
        }
    }

    public void collapse(boolean immediately) {
        if (mInputState == InputState.none) {
            return;
        }

        hideAllInputLayout(immediately);
    }

    public void setReplyMessage(ChatMessageBean messageBean) {
        this.replyMessage = messageBean;
        mBinding.llyReply.setVisibility(VISIBLE);
        String tips = MessageHelper.getReplyMessageTips(messageBean.getMessageData());
        mBinding.tvReplyContent.setText(
                String.format(getContext().getString(R.string.chat_message_reply_someone), tips));

        mBinding.ivReplyClose.setOnClickListener(v -> clearReplyMsg());
        switchInput();
    }

    private void getImp(String extra, String token, String toUserId, String type, String message) {


    }

    public void setReEditMessage(String msgContent) {
        mBinding.chatMessageInputEt.setText(msgContent);
        mBinding.chatMessageInputEt.requestFocus();
        mBinding.chatMessageInputEt.setSelection(mBinding.chatMessageInputEt.getText().length());
        switchInput();
    }

    private void clearReplyMsg() {
        replyMessage = null;
        mBinding.llyReply.setVisibility(GONE);
    }

    private void hideAllInputLayout(boolean immediately) {
        postDelayed(
                () -> {
                    mInputState = InputState.none;
                    KeyboardUtils.hideKeyboard(this);
                    long delay = immediately ? 0 : SHOW_DELAY_TIME;
                    recordShow(false, delay);
                    emojiShow(false, delay);
                    morePanelShow(false, delay);
                },
                immediately ? 0 : ViewConfiguration.getDoubleTapTimeout());
    }

    @Override
    public void onRecordReady() {
        ALog.i(TAG, "onRecordReady");
    }

    @Override
    public void onRecordStart(File audioFile, RecordType recordType) {
        ALog.i(TAG, "onRecordStart");
        startRecord();
    }

    @Override
    public void onRecordSuccess(File audioFile, long audioLength, RecordType recordType) {
        ALog.i(TAG, "onRecordSuccess -->> file:" + audioFile.getName() + " length:" + audioLength);
        endRecord();
        mProxy.sendAudio(audioFile, audioLength, replyMessage);
        clearReplyMsg();
    }

    @Override
    public void onRecordFail() {
        ALog.i(TAG, "onRecordFail");
        endRecord();
    }

    @Override
    public void onRecordCancel() {
        ALog.i(TAG, "onRecordCancel");
        endRecord();
    }

    @Override
    public void onRecordReachedMaxTime(int maxTime) {
        ALog.i(TAG, "onRecordReachedMaxTime -->> " + maxTime);
        mBinding.chatMessageRecordView.recordReachMaxTime(maxTime);
    }

    private void startRecord() {
        mBinding.chatMessageVoiceInTip.setVisibility(VISIBLE);
        mBinding.chatMessageEditInput.setVisibility(INVISIBLE);
        mBinding.chatMessageRecordView.startRecord();
    }

    private void endRecord() {
        mBinding.chatMessageVoiceInTip.setVisibility(GONE);
        mBinding.chatMessageEditInput.setVisibility(VISIBLE);
        mBinding.chatMessageRecordView.endRecord();
    }

    private void onKeyboardShow() {
        ALog.i(TAG, "onKeyboardShow inputState:" + mInputState);
        if (mInputState != InputState.input) {
            hideCurrentInput();
            mInputState = InputState.input;
        }
    }

    private void onKeyboardHide() {
        ALog.i(TAG, "onKeyboardHide inputState:" + mInputState);
        if (mInputState == InputState.input) {
            mInputState = InputState.none;
        }
    }

    private void hideKeyboard() {
        KeyboardUtils.hideKeyboard(mBinding.chatMessageInputEt);
    }

    private void showKeyboard() {
        mBinding.chatMessageInputEt.requestFocus();
        mBinding.chatMessageInputEt.setSelection(mBinding.chatMessageInputEt.getText().length());
        KeyboardUtils.showKeyboard(mBinding.chatMessageInputEt);
    }

    @Override
    public void onTextAdd(String content, int start, int length) {
        if (mInputState != InputState.input) {
            postDelayed(this::switchInput, SHOW_DELAY_TIME);
        }
        mBinding.chatMessageInputEt.getEditableText().insert(start, content);
    }

    @Override
    public void onTextDelete(int start, int length) {
        if (mInputState != InputState.input) {
            postDelayed(this::switchInput, SHOW_DELAY_TIME);
        }
        int end = start + length - 1;
        mBinding.chatMessageInputEt.getEditableText().replace(start, end, "");
    }
}
